package com.commons.dbutils.util;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.commons.dbutils.annotation.Column;

public class VoClassUtils {
	private static SimpleDateFormat sdf = new SimpleDateFormat(
			"yyyy-MM-dd HH:mm:ss");

	private static Map<Class<?>, ClassInfo> classInfoCache = new HashMap<Class<?>, ClassInfo>();

	public static Map<Class<?>, ClassInfo> getAllClassInfo() {
		return classInfoCache;
	}

	private static ClassInfo getClassInfo(Class<?> clazz) throws Exception {
		ClassInfo ci = classInfoCache.get(clazz);
		if (ci == null) {
			ci = new ClassInfo(clazz);
			classInfoCache.put(clazz, ci);
		}
		return ci;
	}

	public static Method getSetterMethod(Class<?> clazz, Field field)
			throws Exception {
		ClassInfo ci = getClassInfo(clazz);
		Map<String,Method> mapSetterMethod = ci.getMapSetMethod();
		return  (mapSetterMethod!=null && mapSetterMethod.size()>0)?mapSetterMethod.get(field.getName()):null;
	}

	public static Method getGetterMethod(Class<?> clazz, Field field) throws Exception {
		ClassInfo ci = getClassInfo(clazz);
		Map<String,Method> mapGetterMethod = ci.getMapGetMethod();
		return (mapGetterMethod!=null && mapGetterMethod.size()>0)? mapGetterMethod.get(field.getName()):null;
	}

	public static List<Field> getIdFields(Class<?> clazz) throws Exception {
		ClassInfo ci = getClassInfo(clazz);
		Collection<Field> coll = (ci.getMapIDField()!=null && ci.getMapIDField().size()>0)?ci.getMapIDField().values():null;
		if(coll==null){
			return null;
		}
		List<Field> fields = new ArrayList<Field>(coll.size());
		for (Field f : coll) {
			fields.add(f);
		}
		return fields;
	}

	public static List<Field> getAllFields(Class<?> clazz) throws Exception {
		ClassInfo ci = getClassInfo(clazz);
		Collection<Field> coll = (ci.getMapAllDBField()!=null && ci.getMapAllDBField().size()>0) ?ci.getMapAllDBField().values():null;
		if(coll==null){
			return null;
		}
		List<Field> fields = new ArrayList<Field>(coll.size());
		for (Field f : coll) {
			fields.add(f);
		}
		return fields;
	}

	public static List<Field> getInsertableFields(Class<?> clazz) throws Exception {
		ClassInfo ci = getClassInfo(clazz);
		Collection<Field> coll = (ci.getMapInsertableField()!=null && ci.getMapInsertableField().size()>0)?ci.getMapInsertableField().values():null;
		if(coll==null){
			return null;
		}
		List<Field> fields = new ArrayList<Field>(coll.size());
		for (Field f : coll) {
			fields.add(f);
		}
		return fields;
	}

	public static List<Field> getUpdatableFields(Class<?> clazz) throws Exception {
		ClassInfo ci = getClassInfo(clazz);
		Collection<Field> coll = ci.getMapUpdatableField().values();
		List<Field> fields = new ArrayList<Field>();
		for (Field f : coll) {
			fields.add(f);
		}
		return fields;
	}

	public static String getTableName(Class<?> clazz) throws Exception {
		return getClassInfo(clazz).getTableName();
	}

	public static String getDBCloumnName(Class<?> clazz, Field f) throws Exception {
		 Map<String, String> dbColumnNames = getClassInfo(clazz).getMapDBColumnName();
		return  dbColumnNames!=null && dbColumnNames.size()>0?dbColumnNames.get(f.getName()):null;
	}

	public static List<Field> getIdentityFields(Class<?> clazz) throws Exception {
		ClassInfo ci = getClassInfo(clazz);
		Collection<Field> coll = ci.getMapIdentityField()!=null && ci.getMapIdentityField().size()>0?ci.getMapIdentityField().values():null;
		if(coll==null){
			return null;
		}
		
		List<Field> fields = new ArrayList<Field>(coll.size());
		for (Field f : coll) {
			fields.add(f);
		}
		return fields;
	}


	public static boolean defaultDBValue(Field f) {
		if (f.isAnnotationPresent(Column.class)) {
			Column column = (Column) f.getAnnotation(Column.class);
			return column.defaultDBValue();
		}
		return false;
	}


	public static String getValue(Object bean, Method method) throws Exception {
		String retValue = "";

		Object valueObj = method.invoke(bean, new Object[0]);
		Class<?> valueType = method.getReturnType();
		if (valueType.equals(String.class)) {
			if (valueObj == null)
				retValue = "''";
			else
				retValue = new StringBuffer("'").append(valueObj.toString() ) .append("'").toString();
		} else if ((valueType.equals(Timestamp.class))
				|| (valueType.equals(java.sql.Date.class))
				|| (valueType.equals(java.util.Date.class))) {
			if (valueObj == null)
				retValue = "''";
			else
				retValue = new StringBuffer("'").append(sdf.format(valueObj)).append("'").toString();
		} else if ((valueType.equals(Boolean.TYPE))
				|| (valueType.equals(Boolean.class))) {
			if ((valueObj != null)
					&& (valueObj.toString().equalsIgnoreCase("true")))
				retValue = "1";
			else {
				retValue = "0";
			}
		} else if (valueObj == null)
			retValue = "null";
		else {
			retValue = valueObj.toString();
		}

		return retValue;
	}
	
	public static String getValue(Object value) throws Exception {
		String retValue = "";
		Class<?> clazz = value.getClass();
		if ((clazz == String.class) || (clazz == java.util.Date.class)
				|| (clazz == java.sql.Date.class))
			retValue = new StringBuffer("'").append(value.toString()).append("'").toString();
		else {
			retValue = value.toString();
		}

		return retValue;
	}
}
